package com.guojian.common.utils;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * http 工具类(基于httpclient4.3.x,且不能出现重复的httpcore或者httpclient包)
 * 
 * @author guojian
 *
 */
public class HttpUtils {

	private static BasicCookieStore cookieStore = new BasicCookieStore();
	private static RequestConfig globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.DEFAULT).build();
	private static CloseableHttpClient commonHttpclient = HttpClients.custom().setDefaultRequestConfig(globalConfig).setDefaultCookieStore(cookieStore).build();

	private static final ObjectMapper jsonMapper = new ObjectMapper();

	private static CloseableHttpClient sslHttpClient = null;
	static {
		SSLContext sslContext = null;
		try {
			sslContext = SSLContext.getInstance("SSL");
			sslContext.init(null, new TrustManager[] { new X509TrustManager() {
				public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				}

				public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				}

				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}

			} }, new SecureRandom());
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		}
		SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
		sslHttpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).setSSLSocketFactory(socketFactory).build();
	}

	/**
	 * 模拟浏览器发送get请求
	 * 
	 * @param url
	 * @return
	 */
	public static String sendGet(String url) {
		return doGetProcess(commonHttpclient, url);
	}

	public static String sendSSLGet(String url) {
		return doGetProcess(sslHttpClient, url);
	}

	private static String doGetProcess(CloseableHttpClient httpClient, String url) {
		HttpGet httpGet = new HttpGet(url);
		setCommonHeads(httpGet);
		String responseMessage = StringUtils.EMPTY;
		try {
			CloseableHttpResponse response = httpClient.execute(httpGet);
			responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
		} catch (Exception e) {
			LogUtils.debug(HttpUtils.class + ": get请求发送失败! " + e.getMessage() + "--URL: " + url);
		}
		LogUtils.debug("http get response: " + responseMessage);
		return responseMessage;
	}

	/**
	 * 将请求的数据封装成json对象返回 设置忽略不明属性@JsonIgnoreProperties(ignoreUnknown = true)
	 * 
	 * @param url
	 * @param c
	 */
	public static <T> T sendGet(String url, Class<T> c) {
		try {
			String responseContent = sendGet(url);
			return jsonMapper.readValue(responseContent, c);
		} catch (Exception e) {
			throw new RuntimeException("http请求的json数据转换成对象失败! " + e.getMessage());
		}
	}

	/**
	 * http post请求
	 * 
	 * @param url
	 * @param nvps
	 * @return
	 */
	public static String commonPost(String url, Map<String, String> nameValues) {
		return doPostProcess(commonHttpclient, url, converMapParamsToList(nameValues));
	}

	/**
	 * https 请求
	 * 
	 * @param url
	 * @param nameValues
	 * @return
	 */
	public static String SSLPost(String url, Map<String, String> nameValues) {
		return doPostProcess(sslHttpClient, url, converMapParamsToList(nameValues));
	}

	public static String JsonPost(String url, String json) {
		HttpPost httpPost = new HttpPost(url);
		setJsonHeads(httpPost);
		String responseMessage = StringUtils.EMPTY;
		try {
			if (json != null) {
				httpPost.setEntity(new StringEntity(json, "UTF-8"));
			}
			CloseableHttpResponse response = commonHttpclient.execute(httpPost);
			responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
		} catch (Exception e) {
			LogUtils.debug(HttpUtils.class + ": post 请求发送失败! " + e.getMessage() + "--URL: " + url);
		}
		LogUtils.debug("http post response: " + responseMessage);
		return responseMessage;
	}

	private static String doPostProcess(CloseableHttpClient httpClient, String url, List<NameValuePair> nvps) {
		HttpPost httpPost = new HttpPost(url);
		setCommonHeads(httpPost);
		String responseMessage = StringUtils.EMPTY;
		try {
			if (nvps != null) {
				httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
			}
			CloseableHttpResponse response = httpClient.execute(httpPost);
			responseMessage = EntityUtils.toString(response.getEntity(), "UTF-8");
		} catch (Exception e) {
			LogUtils.debug(HttpUtils.class + ": post 请求发送失败! " + e.getMessage() + "--URL: " + url);
		}
		LogUtils.debug("http post response: " + responseMessage);
		return responseMessage;
	}

	/**
	 * 参数类型转换
	 * 
	 * @param nameValues
	 * @return
	 */
	private static List<NameValuePair> converMapParamsToList(Map<String, String> nameValues) {
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		if (nameValues != null) {
			for (String name : nameValues.keySet()) {
				nvps.add(new BasicNameValuePair(name, nameValues.get(name)));
			}
		}
		return nvps;
	}

	/**
	 * 设置请求的头部
	 * 
	 * @param request
	 */
	private static void setCommonHeads(HttpUriRequest request) {
		List<Header> headers = new ArrayList<Header>();
		headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36"));
		headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded"));
		headers.add(new BasicHeader("Connection", "keep-alive"));
		headers.add(new BasicHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"));
		Header[] headersObject = new Header[headers.size()];
		request.setHeaders(headers.toArray(headersObject));
	}

	private static void setJsonHeads(HttpUriRequest request) {
		List<Header> headers = new ArrayList<Header>();
		headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36"));
		headers.add(new BasicHeader("Content-type", "application/json; charset=utf-8"));
		headers.add(new BasicHeader("Accept", "application/json"));
		headers.add(new BasicHeader("Connection", "keep-alive"));
		Header[] headersObject = new Header[headers.size()];
		request.setHeaders(headers.toArray(headersObject));
	}

}
